//
//  PullDownRefreshControl.swift
//  SinaBlog
//
//  Created by 李超 on 16/3/28.
//  Copyright © 2016年 lichao. All rights reserved.
//

import UIKit

let animationDurationTime = 0.5

class PullDownRefreshControl: UIView {
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override init(frame: CGRect) {
        //设置默认的frame
        let rect = CGRect(x: 0, y: -refleshViewHight, width: UIScreen.mainScreen().bounds.width, height: refleshViewHight)
        super.init(frame: rect)
        //设置颜色便于调试
        backgroundColor = UIColor.whiteColor()
        //准备相关的控件
        prepareUI()
        loadingView.hidden = true
    }
    //定义高度
    let refleshViewHight:CGFloat = 64
    //加载控件，并做好相关的约束
    func prepareUI(){
        //添加子控件
        addSubview(arrowView)
        addSubview(loadingView)
        addSubview(tipsLable)
        
        //添加约束，封装的空间或者其他的类，尽量少依赖第三方或者其他的类
        arrowView.translatesAutoresizingMaskIntoConstraints = false
        loadingView.translatesAutoresizingMaskIntoConstraints = false
        tipsLable.translatesAutoresizingMaskIntoConstraints = false
        
        addConstraint(NSLayoutConstraint(item: arrowView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: -4))
        
        addConstraint(NSLayoutConstraint(item: arrowView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0))
        
        addConstraint(NSLayoutConstraint(item: loadingView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: -4))
        
        addConstraint(NSLayoutConstraint(item: loadingView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0))
        
        addConstraint(NSLayoutConstraint(item: tipsLable, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: 4))
        
        addConstraint(NSLayoutConstraint(item: tipsLable, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0))
        
    
    }
    //用于记录父控件的属性，避免循环利用需要使用弱引用
    private weak var scrollView:UIScrollView!
    //定义枚举类型,用于记录刷新的相关状态
    enum refreshState:Int{
        //正常状态
        case Normalstate
        //下拉状态
        case pullDownState
        //正在刷新状态
        case refleshingState
    }    
    //用于停止刷新的方法
    func stopRefleshing(){
        currentState = .Normalstate
    }
    //用于开始刷新的方法
    func startRefleshing(){
        currentState = .refleshingState
    }
    //添加无参数无返回值的闭包，用于开始刷新后回调
    var pullDownRefleshCompletionHandler:(() -> ())?
    //用于记录上一次的状态
    var oldRefleshState:refreshState = .Normalstate
    //用于记录当前的刷新状态的枚举类型变量,开始默认为正常状态
    private var currentState = refreshState.Normalstate{
        //根据状态的改变来做相关的业务操作
        didSet{
            switch currentState {
            case .Normalstate:
                tipsLable.text = "下拉刷新"
                arrowView.hidden = false
                loadingView.hidden = true
                //形变归零
                UIView.animateWithDuration(animationDurationTime, animations: { () -> Void in
                    self.arrowView.transform = CGAffineTransformIdentity
                })
              //判断上一次状态是否是在刷新，如果是，则需要退回到原来位置
                if oldRefleshState == .refleshingState{
                    UIView.animateWithDuration(animationDurationTime, animations: { () -> Void in
                        self.scrollView.contentInset.top -= self.refleshViewHight
                    })
                }
            case .pullDownState:
                tipsLable.text = "释放刷新"
                UIView.animateWithDuration(animationDurationTime, animations: { () -> Void in
                    self.arrowView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
                    
                })
            case .refleshingState:
                tipsLable.text = "正在刷新"
                arrowView.hidden = true
                loadingView.hidden = false
                let rotation = CABasicAnimation(keyPath: "transform.rotation")
                rotation.duration = animationDurationTime
                rotation.repeatCount = MAXFLOAT
                rotation.toValue = M_PI * 2
                //需要加上key，否则动画会一直叠加,key可以按照意愿赋值
                loadingView.layer.addAnimation(rotation, forKey: "reflesh")
                UIView.animateWithDuration(animationDurationTime, animations: { () -> Void in
                    self.scrollView.contentInset.top += self.refleshViewHight
                    }, completion: { (Bool) -> Void in
                        
                       self.pullDownRefleshCompletionHandler?()
                })
                
            }
            //在赋值的最后需要将现在的状态赋值给上一次
            oldRefleshState = currentState
        }
        
    }
    
    //监听自己是否要被添加到父控件上
    override func willMoveToSuperview(newSuperview: UIView?) {
        
       let scrollVW = newSuperview as? UIScrollView
        if scrollVW != nil {
            scrollView = scrollVW
             //利用KVO进行观察父控件的滑动offset
            scrollView.addObserver(self, forKeyPath: "contentOffset", options: NSKeyValueObservingOptions.New, context: nil)
        }
        
    }
    //销毁前需要移除KVO，否则会造成崩溃
    deinit{
        scrollView.removeObserver(self, forKeyPath: "contentOffset")
        
    }
    //实现KVO调用的方法,并在此实现相关的业务逻辑
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        //由于已经拿到了父控件，可以直接使用父控件，避免转换相关参数的类型
        //先进行判断是否是在拽动
        if scrollView.dragging{
          //如果是在拖拽则根据相关的偏移值来确定相关的状态
            if currentState == .Normalstate && scrollView.contentOffset.y < -2 * refleshViewHight{
                currentState = .pullDownState
            }else if currentState == .pullDownState && scrollView.contentOffset.y > -2 * refleshViewHight{
                currentState = .Normalstate
            }
        }else if currentState == .pullDownState {
               currentState = .refleshingState
        }
        
    }
    
    //显示箭头的view
    private lazy var arrowView:UIImageView = UIImageView(image: UIImage(named: "tableview_pull_refresh"))
    //显示正在下载的旋转图片
    private lazy var loadingView:UIImageView = UIImageView(image: UIImage(named: "tableview_loading"))
    //显示提示信息的lable
    private lazy var tipsLable:UILabel = {
        let lable = UILabel()
        lable.font = UIFont.systemFontOfSize(14)
        lable.textAlignment = NSTextAlignment.Center
        lable.textColor = UIColor.whiteColor()
        lable.sizeToFit()
        lable.text = "下拉刷新"
        return lable
    }()
    
}

var PullDownRefreshControlKey = "PullDownRefreshControl"
//对scrollView进行拓展，动态添加属性，对刷新控件进行封装
extension UIScrollView{
    
    //不能添加属性只能生成计算性属性，即getter 和setter方法
    private var pullDownRefleshControl:PullDownRefreshControl{
       
        set{
                //将新值添加到属性列表中,策略选择强引用，非原子性
                objc_setAssociatedObject(self, &PullDownRefreshControlKey,newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        
        get{
            
              if let controlView = objc_getAssociatedObject(self, &PullDownRefreshControlKey) as? PullDownRefreshControl {
                   return controlView
              }else{
                    let refleshControlView = PullDownRefreshControl()
                    self.addSubview(refleshControlView)
                    self.pullDownRefleshControl = refleshControlView
                    return refleshControlView
                    }

            }
        
    }
    
    //添加设置回调的方法
    func addPullDownRefleshCompletionHandler(handler:() -> ()){
        self.pullDownRefleshControl.pullDownRefleshCompletionHandler = handler
    }
    //提供开启刷新的方法
    func startRefleshing(){
        self.pullDownRefleshControl.startRefleshing()
    }
    //提供停止刷新的方法
    func endRefleshing(){
        self.pullDownRefleshControl.stopRefleshing()
    }
    
    
}











